<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>

  <body>
    <script>
      // 实现一个mycall方法

      // function fn(){
      //     console.log("fn",this);
      // }
      // var obj = {name:"hello"};
      // fn.call(obj);

      // 1. fn调用的时候  让fn的this指向 obj；
      // 函数里的this 指向一个对象；
      // var myobj = {
      //     name:"hello",
      //     fn:function(){
      //         console.log(this);
      //     }
      // }
      // myobj.fn();  // fn函数里的this 指向 ？

      //2. 直接写mycall函数
      // function mycall(fn,obj){
      //     obj = obj || window;  // 如果传入的是 null 或者是undefined 那么 obj就是window
      //     obj = Object(obj);                  // 如果传入的是简单数据类型 那么把简单数据类型变成包装对象
      //     obj.fn = fn;  // 把函数加入到obj对象里
      //     obj.fn();  // 通过obj对象调用 fn函数
      //     delete obj.fn; // 调用完毕之后 删除fn函数；
      // }

      // mycall(fn,"fdasfdsa");  // 改变fn里的this指向；

      // 3.把mycall函数 挂载在所有函数的原型上方便调用；
      Function.prototype.mycall = function (obj, ...arg) {
        obj = obj || window; // 如果传入的是 null 或者是undefined 那么 obj就是window
        obj = Object(obj); // 如果传入的是简单数据类型 那么把简单数据类型变成包装对象
        obj.fn = this; // 把函数加入到obj对象里
        var res = obj.fn(...arg); // 通过obj对象调用 fn函数
        delete obj.fn; // 调用完毕之后 删除fn函数；
        return res; // 把原来函数的返还值在返还出去；
      };

      // var fn = function(){}

      function fn(a, b, c) {
        console.log("fn", this, a, b, c);
        return "你好";
      }
      var res = fn.mycall({ myname: "hello" }, 1, 2, 3);
      // var res = fn(1,2,3);
      // var res = fn.call({myname:"hello"},1,2);

      console.log(res);
    </script>
  </body>
</html>
